#include "Buffer.h"

#include <cerrno>
#include <sys/uio.h>
#include "tcp/SocketUtils.h"

const char Buffer::kCRLF[] = "\r\n";
const char Buffer::kAnd = '&';

const size_t Buffer::kCheapPrepend;
const size_t Buffer::kInitialSize;

ssize_t Buffer::readFd(int fd, int *savedErrno) {
    // saved an ioctl()/FIONREAD call to tell how much to read
    char extrabuf[65536];
    // 开辟栈内存空间
    struct iovec vec[2];
    // 这个结构体是保存读取的位置的地址的, vec.iov_base是保存buffer的起始地址, iov_len是保存buffer的大小
    const size_t writable = writableBytes();
    vec[0].iov_base = begin() + writerIndex_;
    vec[0].iov_len = writable;
    vec[1].iov_base = extrabuf;
    vec[1].iov_len = sizeof extrabuf;
    const int iovcnt = (writable < sizeof extrabuf) ? 2 : 1;
    // 当缓冲区足够大的时候就选择直接往缓冲区中写入数据, 如果缓冲区大小不够的话, 多余的就往extrabuf中写入数据
    const ssize_t n = sockets::readv(fd, vec, iovcnt);
    // 从文件描述符中读取数据
    if (n < 0) {
        *savedErrno = errno;
    } else if (static_cast<size_t>(n) <= writable) {
        writerIndex_ += n;
        // 如果读取的数据量可以被缓冲区容纳, 就直接移动缓冲区即可
    } else {
        writerIndex_ = buffer_.size();
        append(extrabuf, n - writable);
        // 如果缓冲区大小不足就直接从栈空间中追加
    }
    // if (n == writable + sizeof extrabuf)
    // {
    //   goto line_30;
    // }
    return n;
}